package com.negativeplus.negativeplusscanner;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import android.R.menu;
import android.accounts.NetworkErrorException;
import android.app.Activity;
import android.os.AsyncTask;

public class ScanBarcode {

	private static final String CANCEL_URI = "https://www.tixwise.co.il/he/host/barcode/26336/undo";
	private static final String BARCODE_PASS = "123456";
	private static final String BARCODE_USER_NAME = "negative@aguda.bgu.ac.il";
	private static final String BARCODE_MANAGER_URI = "https://www.tixwise.co.il/he/host/barcode/26336/manager";
	private static final String HTTPS_WWW_TIXWISE_CO_IL_HE_LOGIN = "https://www.tixwise.co.il/he/login";
	private static final CharSequence BARCODE_READY_MESSAGE = "לחץ על השדה בכדי לסרוק כרטיס";
	String uri = BARCODE_MANAGER_URI;
	private String token ;
	private String response;
	private String userId;
	private String purchaseId;
	private MainActivity main;
	private HttpClient client;
	private boolean isCancelAllowed;

	public ScanBarcode(String barcode, MainActivity mainActivity) {
		
		main = mainActivity;
		parseBarcode(barcode);

		// create ssl client
		this.client = new DefaultHttpClient();
		this.client.getConnectionManager().getSchemeRegistry().register(MySSLSocketFactory.getScheme());
	}
	
	public void execute() {
		new ScanBarcodeTask().execute();

	}

	private void parseBarcode(String barcode) {
		boolean tixBarcode = false;
		if (barcode.trim().split(" ").length == 1){
			tixBarcode = true; 
		}
		if(tixBarcode){
			this.userId = barcode;
		}else{
			String[] splitBarcode = barcode.split(" ");
			this.userId  = splitBarcode[0];
			this.purchaseId = splitBarcode[1];
		}

	}

	private String login(HttpClient client) throws URISyntaxException,
	IOException, ClientProtocolException, UnsupportedEncodingException, NetworkErrorException {
		URI website = new URI(uri); 
		HttpGet request = new HttpGet();
		request.setURI(website);
		HttpResponse getCertResponse = client.execute(request);
		HttpEntity getCertContant = getCertResponse.getEntity();
		String contant = EntityUtils.toString(getCertContant);
		if (contant.contains(BARCODE_READY_MESSAGE)){
			return contant;
		}else {
			String username = BARCODE_USER_NAME;
			String pass = BARCODE_PASS;
			HttpPost login = new HttpPost(HTTPS_WWW_TIXWISE_CO_IL_HE_LOGIN);
			login.addHeader("Referer", BARCODE_MANAGER_URI);
			login.setHeader("Content-Type", "application/x-www-form-urlencoded");
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();	
			nvps.add(new BasicNameValuePair("signin[username]", username));
			nvps.add(new BasicNameValuePair("signin[password]", pass));
			token = findToken(contant);
			nvps.add(new BasicNameValuePair("signin[_csrf_token]", token));
			login.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
			HttpResponse loginResponse = client.execute(login);
			HttpEntity loginContant = loginResponse.getEntity();
			contant = EntityUtils.toString(loginContant);
			if (contant.contains(BARCODE_READY_MESSAGE) == false){
				throw new NetworkErrorException("Failed To Login");
			}
			return 	contant;
		}
	}

	private HttpEntity sendUserId(HttpClient client, String token)
			throws UnsupportedEncodingException, IOException,
			ClientProtocolException {
		HttpPost sendUserId = new HttpPost(BARCODE_MANAGER_URI);
		sendUserId.addHeader("Referer", BARCODE_MANAGER_URI);
		sendUserId.setHeader("Content-Type", "application/x-www-form-urlencoded");
		List <NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("barcode", this.userId));
		nvps.add(new BasicNameValuePair("_csrf_token", token));
		sendUserId.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8));
		HttpResponse response = client.execute(sendUserId);
		HttpEntity sendUserIdRespone = response.getEntity();
		return sendUserIdRespone;
	}

	private boolean onePurchaseForId(String sendUserIdRespone) {
		Document doc =  Jsoup.parse(sendUserIdRespone);
		boolean ans = doc.select("[data-role=content]").select("p").first().hasAttr("style");
		if (purchaseId == null){
			try{
				purchaseId = doc.select("[name=purchase_id]").first().attr("value");
			}catch (Exception e){
				this.isCancelAllowed = false;
			}
		}
		return ans;
	}

	private HttpEntity sendPurchaseId(HttpClient client, String token)
			throws UnsupportedEncodingException, IOException,
			ClientProtocolException {
		List<NameValuePair> nvps;
		HttpResponse response;
		HttpPost sendPurchaseId = new HttpPost(BARCODE_MANAGER_URI);
		sendPurchaseId.addHeader("Referer", BARCODE_MANAGER_URI);
		sendPurchaseId.setHeader("Content-Type", "application/x-www-form-urlencoded");
		nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("purchase_id", this.purchaseId));
		nvps.add(new BasicNameValuePair("_csrf_token", token));
		sendPurchaseId.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
		response = client.execute(sendPurchaseId);
		return response.getEntity();
	}

	public String getResponse() {
		return response;
	}



	private String findToken(String contant) {
		Document doc = Jsoup.parse(contant);
		String ans;
		try{
			if (token == null){
				ans = doc.getElementById("signin__csrf_token").attr("value");
				token = ans;
			}else{
				ans = doc.getElementById("csrf_token").attr("value");
				token = ans;
			}
		}catch (Exception e){
			ans = token;
		}
		return ans;
	}

	private void extractAnswer(String sendPurchaseIdResponseContant) {
		Document doc = Jsoup.parse(sendPurchaseIdResponseContant);
		Element contentDiv = doc.select("[data-role=content").first();
		String resultHeader;
		try{
			resultHeader = contentDiv.select("p").first().text()+"\n";
		}catch (Exception e){
			this.main.setAnswer(Utils.tr2nl(contentDiv.html()), false);
			return;
		}
		boolean success = contentDiv.select("p").first().attr("style").equals("color:green");

		if (success){
			this.isCancelAllowed = true;
			try{
				Element orderDetails = contentDiv.select("table").first();
				String ticketTypeHeader = contentDiv.select("u").first().text();
				Element ticketTypeList = contentDiv.select("ul").first();
				String ans = resultHeader+"\n";
				for (Element e : orderDetails.select("tr")) {
					ans+=e.text()+"\n";
				}
				ans+=ticketTypeHeader+"\n"+ticketTypeList.text();
				this.main.setAnswer(ans, success);
			}
			catch (Exception e){
				//cancel
				if (resultHeader.startsWith("הביטול")){
					this.main.setAnswer(resultHeader, success);
				}
			}
		}
		else{
			this.main.setAnswer(resultHeader.replace("עקסה", "עסקה"), success);
		}
	}

	public void cancelLastScan() {
		if (isCancelAllowed == false){
			DialogManager.showOKDialog(main, false, main.getString(R.string.cancel_error_title), main.getString(R.string.cancel_error_message));
			return;
		}
		new cancelTask().execute();
	}

	private class ScanBarcodeTask extends AsyncTask<Void, Void, Void> {
		@Override
		protected Void doInBackground(Void... params) {
			try {

				// login to TixWise barcode interface
				String loginResponseContant = null;
				try {
					loginResponseContant = login(client);
				} catch (NetworkErrorException e) {
					DialogManager.showOKDialog(main, true, main.getString(R.string.error_header),main.getString(R.string.try_again) );
					return null;
				}
				token = findToken(loginResponseContant);

				// send the id from the scanned barcode
				HttpEntity sendUserIdRespone = sendUserId(client, token);
				String sendUserIdResponsContant = EntityUtils.toString(sendUserIdRespone);
				if (onePurchaseForId(sendUserIdResponsContant)){
					extractAnswer(sendUserIdResponsContant);
					return null;
				}
				token = findToken(sendUserIdResponsContant);


				// send the purchase id from the scanned barcode
				HttpEntity sendPurchaseIdResponse = sendPurchaseId(client, token);
				String sendPurchaseIdResponseContant = EntityUtils.toString(sendPurchaseIdResponse);
				token = findToken(sendPurchaseIdResponseContant);
				extractAnswer(sendPurchaseIdResponseContant);
			}catch (Exception e){
				DialogManager.showOKDialog(main, true, main.getString(R.string.error_header),main.getString(R.string.try_again) );
				return null;
			}
			return null;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			DialogManager.showLoadingDialog(main);
		}

		@Override
		protected void onPostExecute(Void result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
			DialogManager.dismissLoadingDialog();
		}
	}
	
	private class cancelTask extends AsyncTask<Void, Void, Void>{

		@Override
		protected Void doInBackground(Void... params) {
			try{
				HttpPost cancelRequest = new HttpPost(CANCEL_URI);
				cancelRequest.addHeader("Referer", BARCODE_MANAGER_URI);
				cancelRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
				List <NameValuePair> nvps = new ArrayList<NameValuePair>();
				nvps.add(new BasicNameValuePair("purchase_id", purchaseId));
				nvps.add(new BasicNameValuePair("_csrf_token", token));
				cancelRequest.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8));
				HttpResponse response = client.execute(cancelRequest);
				HttpEntity cancelRequestRespone = response.getEntity();
				String cancelRequestContant = EntityUtils.toString(cancelRequestRespone);
				token = findToken(cancelRequestContant);
				extractAnswer(cancelRequestContant);
				isCancelAllowed = false;
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		
			return null;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			DialogManager.showLoadingDialog(main);
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			DialogManager.dismissLoadingDialog();
		}
		
	}
}

